package com.changpeng.shake.common.utils;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.xml.bind.DatatypeConverter;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.List;
import java.util.TreeMap;

@Slf4j
@Component
public class RepeatSubmitUtil {

    @Autowired
    private RedisUtil redisUtil;

    public static String digestParamMD5(String paramJson, String... excludeKey) {
        String digestMD5 = paramJson;
        TreeMap paramTreeMap = JSON.parseObject(paramJson, TreeMap.class);
        if(excludeKey != null) {
            List<String> excludeKeyList = Arrays.asList(excludeKey);
            if(!excludeKeyList.isEmpty()) {
                for (String key : excludeKeyList) {
                    paramTreeMap.remove(key);
                }
            }
        }
        String json = JSON.toJSONString(paramTreeMap);
        digestMD5 = jdkMD5(json);
        return digestMD5;
    }

    private static String jdkMD5(String src) {
        String res = null;
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            byte[] mdBytes = messageDigest.digest(src.getBytes());
            res = DatatypeConverter.printHexBinary(mdBytes);
        } catch (Exception e) {
            log.error("",e);
        }
        return res;
    }

    /**
     * 判断当前用户下的同一方法中的参数是否存在重复请求
     * @param requestParam 请求参数
     * @param userId 当前用户ID
     * @param method 方法名称
     * @param excludeKey 需要排除的字段。有的请求参数可能包含时间字段，值会不同，从而影响判断，需要排除
     * @return true:重复提交
     */
    public boolean isRepeatRequest(Object requestParam, Long userId, String method, String... excludeKey) {
        String requestParamJson = JSON.toJSONString(requestParam);
        System.out.println(requestParamJson);
        String requestParamMd5 = RepeatSubmitUtil.digestParamMD5(requestParamJson, excludeKey);
        System.out.println(requestParamMd5);

        String key = "repeat:U=" + userId + "M=" + method + "P=" + requestParamMd5;
        long expireTime = 1000;// 1000毫秒过期，1000ms内的重复请求会认为重复
        long expireAt = System.currentTimeMillis() + expireTime;
        String val = "expireAt@" + expireAt;
        // key设置失败则代表已经存在，说明是重复请求
        return !this.redisUtil.setNX(key, val, expireTime);
    }
}
